/**    
 * 文件名：UnRentService.java</br>
 *    
 * 版本信息：v1.0</br>
 * 日期：2017年8月22日</br>
 * © 2005-2017 雷技信息科技（上海）有限公司版权所有</br>
 *
 */
package com.logic.landseaserver.models.unrent.service;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.logic.landseaserver.common.LandeaConstants;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.logic.common.security.SecurityUtils;
import com.logic.landseaserver.common.LandeaConstants.CheckType;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.common.exception.ResultCodes.PaymentResultCode;
import com.logic.landseaserver.common.exception.ResultCodes.UnRentResultCode;
import com.logic.landseaserver.common.util.DateUtil;
import com.logic.landseaserver.common.util.LandSeaUtil;
import com.logic.landseaserver.domain.Bill;
import com.logic.landseaserver.domain.CheckFeeList;
import com.logic.landseaserver.domain.CheckList;
import com.logic.landseaserver.domain.Contract;
import com.logic.landseaserver.models.billcancel.bean.MeterReadResp;
import com.logic.landseaserver.persistence.read.BillReadMapper;
import com.logic.landseaserver.persistence.read.CheckFeeListReadMapper;
import com.logic.landseaserver.persistence.read.CheckListReadMapper;
import com.logic.landseaserver.persistence.read.ContractReadMapper;
import com.logic.landseaserver.persistence.read.ExpensesReadMapper;
import com.logic.landseaserver.persistence.write.CheckFeeListWriteMapper;
import com.logic.landseaserver.persistence.write.CheckListWriteMapper;
import com.logic.landseaserver.ws.dto.CheckFeeListDTO;
import com.logic.landseaserver.ws.dto.CheckListDTO;
import com.logic.system.domain.SystemFile;
import com.logic.system.service.impl.FileService;

/**
 *
 * 项目名称：system-server</br>
 * 类名称：UnRentService</br>
 * 类描述：退租服务</br>
 * 创建人：Aaron</br>
 * 创建时间：2017年8月22日 下午5:41:10</br>
 * 
 * @version 1.0
 *
 */
@Service
public class UnRentService
{
    private static final Logger LOGGER = LoggerFactory.getLogger(UnRentService.class);
    
    @Autowired
    private CheckListWriteMapper checkListWriteMapper;
    
    @Autowired
    private CheckListReadMapper checkListReadMapper;
    
    @Autowired
    private CheckFeeListWriteMapper checkFeeListWriteMapper;
    
    @Autowired
    private CheckFeeListReadMapper checkFeeListReadMapper;
    
    @Autowired
    private FileService fileService;
    
    @Autowired
    private ExpensesReadMapper expensesReadMapper;
    
    @Autowired
    private ContractReadMapper contractReadMapper;
    
    @Autowired
    private BillReadMapper billReadMapper;
    
    /**
     * 
     * [简要描述]：保存退租交割信息</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-08-22)</br>
     *
     * @param checkListDTO
     * @throws LandseaException
     *
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {LandseaException.class, Exception.class})
    public void saveUnRentCheckList(CheckListDTO checkListDTO)
        throws LandseaException
    {
        try
        {
            Map<String, Object> queryParam = new HashMap<String, Object>();
            queryParam.put("contractId", checkListDTO.getContractId());
            queryParam.put("checkType", CheckType.UN_RENT);
            
            // 通过合同查询roomId
            Contract contract = contractReadMapper.selectByPrimaryKey(checkListDTO.getContractId());
            if (null == contract)
            {
                throw LandseaException.createException(PaymentResultCode.E00150011);
            }
          if(checkListDTO.getOprType().equals(LandeaConstants.ReRentType.OFFRENT) ||
                  checkListDTO.getOprType().equals(LandeaConstants.ReRentType.CHANGE) ||
                  checkListDTO.getOprType().equals(LandeaConstants.ReRentType.TURN)){
                CheckList checkList = checkListReadMapper.selectByContractIdAndType(queryParam);
                if (null == checkList) {
                    // 新增
                    insertCheckListInfo(checkListDTO, contract.getRoomId());
                    addCheckFeeList(checkListDTO, contract.getRoomId());
                    return;
                }else{
                    updateCheckList(checkListDTO, checkList);
                    updateCheckFeeList(checkListDTO, contract);
                    return;
                }
            } else if(checkListDTO.getOprType().equals(LandeaConstants.ReRentType.RERENT)){
                List<CheckFeeListDTO> checkFeeLists = checkFeeListReadMapper.selectByContractIdAndCheckType(queryParam);
                if(checkFeeLists.size()==0){
                    addCheckFeeList(checkListDTO, contract.getRoomId());
                    return;
                }else{
                    updateCheckFeeList(checkListDTO, contract);
                    return;
                }
            }
        }
        catch (LandseaException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            LOGGER.error("saveUnRentCheckList|保存退租交割单失败.", e);
            throw LandseaException.createException(UnRentResultCode.E00350002);
        }
    }

    private void updateCheckList(CheckListDTO checkListDTO, CheckList checkList) {
        // 以下是修改
        CheckList checkListUpdate = new CheckList();
        checkListUpdate.setId(checkList.getId());
        checkListUpdate.setContractId(checkList.getContractId());

        // 类型设置为：退租
        checkListUpdate.setCheckType(CheckType.UN_RENT);

        // 保存退房物品交割单附件
        setCheckListByCheckListDTO(checkListUpdate, checkListDTO);
        checkListUpdate.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());

        checkListWriteMapper.updateByPrimaryKeySelective(checkListUpdate);
    }

    private void updateCheckFeeList(CheckListDTO checkListDTO, Contract contract) throws LandseaException {
        // 修改费用交割单
        List<CheckFeeListDTO> checkFeeList = checkListDTO.getCheckFeeListAll();
        if (CollectionUtils.isNotEmpty(checkFeeList))
        {
            for (CheckFeeListDTO checkFeeListDTO : checkFeeList)
            {
                CheckFeeList checkFeeListUpdate = new CheckFeeList();
                setCheckFeeListByCheckListDTO(checkFeeListUpdate, checkFeeListDTO);
                checkFeeListUpdate.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
                // 类型设置为：退租
                checkFeeListUpdate.setCheckType(CheckType.UN_RENT);

                // 检查退租交割单信息(读数和抄表时间)
                checkLastDegree(contract.getRoomId(), checkFeeListUpdate);

                checkFeeListWriteMapper.updateByPrimaryKeySelective(checkFeeListUpdate);
            }
        }
    }

    /**
     * 
     * [简要描述]：查询退租交割单信息</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-08-23)</br>
     *
     * @param contractId 合同编号
     * @return CheckListDTO
     * @throws LandseaException
     *
     */
    public CheckListDTO getUnRentCheckList(Integer contractId,String oprType) throws LandseaException
    {
        // 不需要查询上次读数，直接查询退租的
        CheckListDTO unCheckListDTO = getCheckListByCheckType(contractId, CheckType.UN_RENT,oprType);
        
        if (null == unCheckListDTO)
        {
            // 需要查询上次读数
            unCheckListDTO = getCheckListByCheckType(contractId, CheckType.IN_COMING,oprType);
        }
        
        return unCheckListDTO;
    }
    
    /**
     * 
     * [简要描述]：</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-08-23)</br>
     *
     * @param contractId
     * @param checkType 入住交割单或者退租交割单
     * @return
     * @throws LandseaException
     *
     */
    public CheckListDTO getCheckListByCheckType(Integer contractId, Integer checkType,String oprType) throws LandseaException
    {
        try
        {
            Map<String, Object> queryParam = new HashMap<String, Object>();
            queryParam.put("contractId", contractId);
            queryParam.put("checkType", checkType);
            CheckListDTO checkList = checkListReadMapper.getCheckListDetail(queryParam);
            if (null == checkList)
            {
                if(oprType.equals(LandeaConstants.ReRentType.OFFRENT)
                        || oprType.equals(LandeaConstants.ReRentType.CHANGE)
                    || oprType.equals(LandeaConstants.ReRentType.TURN)){
                    return checkList;
                }else if (oprType.equals(LandeaConstants.ReRentType.RERENT)){
                    checkList = new CheckListDTO();
                    checkList.setCheckType(checkType);
                    checkList.setContractId(contractId);
                }
            }

            // 获取费用交割单详情
            List<CheckFeeListDTO> feeList = checkFeeListReadMapper.selectByContractIdAndCheckType(queryParam);
            if (oprType.equals(LandeaConstants.ReRentType.RERENT) && feeList.size()==0){
                return null;
            }

            // 如果是第一次，要查询最后一次抄表数据
            if (CheckType.IN_COMING == checkType && null != feeList)
            {
                // 通过合同查询roomId
                Contract contract = contractReadMapper.selectByPrimaryKey(contractId);
                if (null == contract)
                {
                    throw LandseaException.createException(PaymentResultCode.E00150011);
                }
                
                Map<String,Object> paramMap = new HashMap<String,Object>();
                paramMap.put("roomId", contract.getRoomId());
                for (CheckFeeListDTO checkFeeListDto : feeList)
                {
                    paramMap.put("expenseType", checkFeeListDto.getType());
                    // 查询最后一次读数
                    MeterReadResp meterReadResp = selectLastMeterRead(contractId,checkFeeListDto.getType(), contract.getRoomId()); 
                    if (null != meterReadResp)
                    {
                        // 抄表日期
                        checkFeeListDto.setInDate(meterReadResp.getReadMeterTime());
                        // 抄表读数
                        checkFeeListDto.setConsumptionEnd(meterReadResp.getDegree());
                    }
                }
            }
            
            checkList.setCheckFeeListAll(feeList);
            
            // 获取入住交割文件信息
            String checkInFiles = checkList.getCheckinFiles();
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(checkInFiles))
            {
                String[] checkInFileArr = checkInFiles.split(",");
                
                List<SystemFile> imageList = new ArrayList<SystemFile>();
                
                for (String imageId : checkInFileArr)
                {
                    SystemFile systemFileImage = (SystemFile)fileService.get(imageId);
                    imageList.add(systemFileImage);
                }
                checkList.setCheckinFilesImgs(imageList);
            }
            
            // 获取退租交割文件信息
            String checkOutFiles = checkList.getCheckoutFiles();
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(checkOutFiles))
            {
                String[] checkOutFilesArr = checkOutFiles.split(",");
                
                List<SystemFile> imageList = new ArrayList<SystemFile>();
                
                for (String imageId : checkOutFilesArr)
                {
                    SystemFile systemFileImage = (SystemFile)fileService.get(imageId);
                    imageList.add(systemFileImage);
                }
                checkList.setCheckoutFilesImgs(imageList);
            }
            
            // 获取朗诗寓公约文件
            String conventionFiles = checkList.getConventionFiles();
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(conventionFiles))
            {
                String[] conventionFilesArr = conventionFiles.split(",");
                
                List<SystemFile> imageList = new ArrayList<SystemFile>();
                
                for (String imageId : conventionFilesArr)
                {
                    SystemFile systemFileImage = (SystemFile)fileService.get(imageId);
                    imageList.add(systemFileImage);
                }
                checkList.setConventionFilesImgs(imageList);
            }
            
            return checkList;
        }
        catch (LandseaException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            LOGGER.error("getCheckListByCheckType|查询交割单失败.", e);
            throw LandseaException.createException(UnRentResultCode.E00350003);
        }
    }
    
    private MeterReadResp selectLastMeterRead(Integer contractId, String expenseType, Integer roomId) throws ParseException
    {
        MeterReadResp resp = new MeterReadResp();
        Map<String, Object> pmap = new HashMap<String, Object>();
        pmap.put("expenseType", expenseType);
        pmap.put("contractId", contractId);
        Bill bill = billReadMapper.selectNewlyPayBill(contractId);
        if (null == bill)
        {
            return null;
        }
        //如果只有首期付款了，只能从交割单里面读取数据
        if ("首期账单".equals(bill.getName()))
        {
           resp = checkFeeListReadMapper.selectByContractIdAndType(pmap);
        }
        else
        {
            String billMonth = LandSeaUtil.getMonthlyBillMonth(bill.getBillMonth());
            DateUtil dateUtil = new DateUtil();
            String billMonth1 = dateUtil.getDateFormat(billMonth);
            pmap.put("billMonth", billMonth1);
            pmap.put("roomId", roomId);
            resp = expensesReadMapper.selectPayBillReadMeter(pmap);
            if(resp==null){
                resp = checkFeeListReadMapper.selectByContractIdAndType(pmap);
            }
        }
        return resp;
    }

    /**
     * 
     * [简要描述]：新增退租交割单</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-08-23)</br>
     *
     * @param checkListDTO
     * @throws LandseaException
     *
     */
    public void insertCheckListInfo(CheckListDTO checkListDTO, Integer roomId) throws LandseaException
    {
        try
        {

            CheckList checkList = new CheckList();
            setCheckListByCheckListDTO(checkList, checkListDTO);
            checkList.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
            checkList.setCheckType(CheckType.UN_RENT);
            checkListWriteMapper.insertSelective(checkList);
        }
        catch (Exception e)
        {
            LOGGER.error("insertCheckListInfo|新增退租交割单失败.", e);
            throw LandseaException.createException(UnRentResultCode.E00350004);
        }
    }

    private void addCheckFeeList(CheckListDTO checkListDTO, Integer roomId) throws LandseaException {
        // 插入费用交割单
        List<CheckFeeListDTO> checkFeeList = checkListDTO.getCheckFeeListAll();
        if (CollectionUtils.isNotEmpty(checkFeeList))
        {
            // 因为是新增，为了防止重复插入，先删除再新增
            checkFeeListWriteMapper.deleteCheckFeeList(checkListDTO.getContractId(), CheckType.UN_RENT);

            for (CheckFeeListDTO checkFeeListDTO : checkFeeList)
            {
                checkFeeListDTO.setCheckType(CheckType.UN_RENT);
                CheckFeeList checkFeeListInsert = new CheckFeeList();
                checkFeeListInsert.setCheckType(checkFeeListDTO.getCheckType());
                setCheckFeeListByCheckListDTO(checkFeeListInsert,checkFeeListDTO);
                checkFeeListInsert.setId(null);
                checkFeeListInsert.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());

                // 检查退租交割单信息(读数和抄表时间)
                checkLastDegree(roomId, checkFeeListInsert);

                checkFeeListWriteMapper.insertSelective(checkFeeListInsert);
            }
        }
    }

    /**
     * 
     * [简要描述]：更新赋值</br>
     * [详细描述]：</br>
     * [作者]：Aaron(2017-08-22)</br>
     *
     * @param checkList
     * @param checkListDTO
     *
     */
    public void setCheckListByCheckListDTO(CheckList checkList, CheckListDTO checkListDTO)
    {
        if (!StringUtils.isEmpty(checkListDTO.getId()))
        {
            checkList.setId(checkListDTO.getId());
        }
        if (!StringUtils.isEmpty(checkListDTO.getContractId()))
        {
            checkList.setContractId(checkListDTO.getContractId());
        }
        if (!StringUtils.isEmpty(checkListDTO.getCheckinFiles()))
        {
            checkList.setCheckinFiles(checkListDTO.getCheckinFiles());
        }
        if (!StringUtils.isEmpty(checkListDTO.getCheckoutFiles()))
        {
            checkList.setCheckoutFiles(checkListDTO.getCheckoutFiles());
        }
        if (!StringUtils.isEmpty(checkListDTO.getConventionFiles()))
        {
            checkList.setConventionFiles(checkListDTO.getConventionFiles());
        }
        if (!StringUtils.isEmpty(checkListDTO.getComments()))
        {
            checkList.setComments(checkListDTO.getComments());
        }
        if (!StringUtils.isEmpty(checkListDTO.getUserId()))
        {
            checkList.setUserId(checkListDTO.getUserId());
        }
    }
    
    public void setCheckFeeListByCheckListDTO(CheckFeeList checkList, CheckFeeListDTO checkListDTO)
    {
        if (!StringUtils.isEmpty(checkListDTO.getId()))
        {
            checkList.setId(checkListDTO.getId());
        }
        if (!StringUtils.isEmpty(checkListDTO.getContractId()))
        {
            checkList.setContractId(checkListDTO.getContractId());
        }
        if (!StringUtils.isEmpty(checkListDTO.getType()))
        {
            checkList.setType(checkListDTO.getType());
        }
        if (!StringUtils.isEmpty(checkListDTO.getInDate()))
        {
            checkList.setInDate(checkListDTO.getInDate());
        }
        if (!StringUtils.isEmpty(checkListDTO.getConsumptionEnd()))
        {
            checkList.setConsumptionEnd(checkListDTO.getConsumptionEnd());
        }
    }
    
    /**
     * 
     * [简要描述]：检查退租交割单读数</br>
     * [详细描述]：抄表时间、读数不能比上次小</br>
     * [作者]：Aaron(2017-09-20)</br>
     *
     * @param roomId
     * @param checkFeeList 
     * @return
     * @throws LandseaException
     *
     */
    private void checkLastDegree(Integer roomId, CheckFeeList checkFeeList) throws LandseaException
    {
        try
        {
            // 查询最后一次读数
            Map<String,Object> paramMap = new HashMap<String,Object>();
            paramMap.put("roomId", roomId);
            paramMap.put("expenseType", checkFeeList.getType());
            // 查询最后一次读数
            MeterReadResp meterReadResp = selectLastMeterRead(checkFeeList.getContractId(),checkFeeList.getType(),roomId); 
            // 如果没有，则不需要校验
            if (null == meterReadResp)
            {
                return;
            }
            
            // 校验时间,可以相等，但不能小于
            int result = DateUtil.compareTime(checkFeeList.getInDate(), meterReadResp.getReadMeterTime());
            if (-1 == result)
            {
                throw LandseaException.createException(UnRentResultCode.E00350006);
            }
            
            // 抄表读数
            Double inputDegree = checkFeeList.getConsumptionEnd();
            // 最后一次的读数
            Double lastDegree = meterReadResp.getDegree();
            if (null == lastDegree)
            {
             return;   
            }
            
            // 可以相等，但不能小于
            if (null == inputDegree || inputDegree.doubleValue() < lastDegree.doubleValue())
            {
                throw LandseaException.createException(UnRentResultCode.E00350007); 
            }
        }
        catch (LandseaException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            LOGGER.error("checkLastDegree|检查退租交割单信息数据异常.", e);
            throw LandseaException.createException(UnRentResultCode.E00350008);
        }
    }
}
